/**
 * 
 */
package com.amkai.aes.webservice.binary.objecthandler;

import java.io.Serializable;
import java.util.TimeZone;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.amkai.aes.aescommon.AESSettings;
import com.amkai.aes.aescommon.exceptions.AccessException;
import com.amkai.aes.aescommon.login.errorcodes.LoginErrorCodes;
import com.amkai.aes.aescommon.service.binary.job.LoginJob;
import com.amkai.aes.aescommon.service.result.LoginResult;
import com.amkai.aes.generatedbeans.organization.BusinessGroup;
import com.amkai.aes.generatedbeans.organization.Department;
import com.amkai.aes.generatedbeans.passport.Passport;
import com.amkai.aes.generatedbeans.security.PassportAuditKind;
import com.amkai.aes.generatedbeans.tree.NodeKind;
import com.amkai.aes.server.exception.RoleException;
import com.amkai.aes.server.hibernate.managment.PassportManager;
import com.amkai.aes.server.manager.PassportSecurityManager;
import com.amkai.aes.server.manager.security.AOServerSecurityManager;
import com.amkai.aes.server.session.Connection;
import com.amkai.aes.server.session.ServiceSessionManager;
import com.amkai.aes.server.utils.AeMemoryChecker;
import com.amkai.aes.webservice.binary.JobObjectHandler;
import com.amkai.common.extensions.hibernate.config.SiteManager;
import com.amkai.common.extensions.hibernate.config.manager.SessionManager;
import com.amkai.common.extensions.hibernate.tools.AuditTrailManager;
import com.amkai.extensions.server.version.VersionControl;

/**
 * @author johnny
 *
 */
public class LoginHandler implements JobObjectHandler<LoginJob, Serializable, LoginResult>{

	private static final Log log = LogFactory.getLog(LoginHandler.class);

	
	public LoginResult process(LoginJob job, Serializable object) throws Exception {
		AeMemoryChecker.checkMemory();
		LoginResult result = new LoginResult();
		result.timeZone = TimeZone.getDefault();
		LoginErrorCodes code = LoginErrorCodes.FAILED;
		boolean isLastChance = false;
		try {
			VersionControl wc = new VersionControl();
			wc.versionControll(job.getClientCodeVersion(),job.getClientDBVersion(), job.getTimeZone());
			PassportManager passportManager = new PassportManager();
//			SecurityManager sec = new SecurityManager(passporAdmin	tManager.getSessionManager());
			code = passportManager.canLogin(job.getPassportName(), job.getPassword());
			
			if (code.equals(LoginErrorCodes.INVALIDUSER)) {
				//Szabi 	 AES-5573
				int invalidCount = PassportSecurityManager.UpdateFailedLogins(job.getPassportName(), job.getPassword(), job.getClientHost(), job.getDepartmentId());
				if (invalidCount == Integer.MIN_VALUE) {
					code = LoginErrorCodes.NOTACTIVE;
				}
				else {
					isLastChance = invalidCount == PassportSecurityManager.MAX_INVALID_LOGIN - 1; 					
					//#12461
					result.setLastChanceToTryLogin(isLastChance);
					if (isLastChance) {
						code = LoginErrorCodes.LAST_CHANCE_TO_LOGIN_BEFORE_LOCK;
					}
				}
			}
			
			
			if (code.equals(LoginErrorCodes.SUCCESS)) {
				if (!job.isCheckLogin()) {
										
					
					Passport passport = passportManager.getPassport();
							
					Connection conn = ServiceSessionManager.getConnection();
					conn.setRuntimePassport(passportManager.getPassport());
					conn.setClientHost(job.getClientHost());
					if (job.reLogin) {
						log.info(String.format("ReLogin (recreating the lost session) [%s@%s]", passport.getName(), job.getClientHost()));
					}
					
					SessionManager sm = SiteManager.Start();
					Department department = null;
					try {
						sm.openSession();
//						department = (Department) sm.get(Department.class, job.getDepartmentId());
						//#12512
						String queryString = "SELECT be FROM Department be LEFT JOIN FETCH be.parent WHERE be.id = :beId";
						department = (Department)sm.execute(queryString).setParameter("beId", job.getDepartmentId()).uniqueResult();
						if (department == null) {							
							code = LoginErrorCodes.DEPARTMENTFAILED;
						} else {
							// KKORNEL: AES-6856
							AOServerSecurityManager ssm = new AOServerSecurityManager(sm);
							if (!ssm.isPassportHasGotNoAccessInDepartment(passport, department)) {
								// KKORNEL: AES-13304
								browseDepartment(result, sm, department);
								// TODO AES-2518 Allow to log into any departments
								// sec.checkPermission(passport, department, sec.getLoginPermission());
								conn.setConnected(passport.isActive());
								
								//Szabi 	 AES-5573
								PassportSecurityManager.ClearFailedLogins(passport, job.getClientHost());					
								PassportSecurityManager.AddPassportAudit(passport, job.getClientHost(),PassportAuditKind.LOGIN);					
								
								// KKORNEL: AES-7239
								result.setAuditTrail(AuditTrailManager.getInstance(sm).createLoginAuditTrailInTransaction(sm, AESSettings.getServerSettings().getAesAuditTrail(), passport));
								ServiceSessionManager.getConnection().setLoginAuditTrail(result.getAuditTrail());
							} else {
								code = LoginErrorCodes.PASSPORT_HAS_NO_ACCESS_ROLE_IN_THIS_DEPARTMENT;
							}
						}												
					}
					catch (Exception ex) {
						if (ex instanceof RoleException) {
							code = LoginErrorCodes.DEPARTMENTFAILED;
						}
						else {
							throw ex;
						}
					}
					finally {
						sm.closeSession();
					}
					ServiceSessionManager.setClientTimeZone(job.getTimeZone());
					result.setPassport(passport);
				}
			}
			else {
				result.setPassport(null);
			}
		}
		catch (Exception ex) {
			if (ex instanceof AccessException) {
				code = ((AccessException)ex).getCode();
				result.setObjects(((AccessException)ex).getObjects());
			}
			else {
				log.error("",ex);
				code = LoginErrorCodes.FAILED;
			}
		}
		result.setErrorCode(code);
		return result;
	}
	
	// KKORNEL: AES-13304 - sm parameter is added
	public static void browseDepartment(LoginResult result, SessionManager sm, Department department) throws Exception {
		// Szabi: AES-5389	
		if (department.getMainOffice() != null) {
			department.getMainOffice().getId();
			department.getMainOffice().getName();
		}
		if (result != null)
			result.setDepartment(department);
		if (department.getDepartmentType() != null) {
			department.getDepartmentType().getKind();
			department.getFederalTaxId();
			// read all address related properties
			if (department.getLocation() != null) {
				if (department.getLocation().getPhone() != null)
					department.getLocation().getPhone().getNumber();
				department.getLocation().getExtendedZip();
				department.getLocation().getFax();
				department.getLocation().getLine1();
				department.getLocation().getLine2();
				if (department.getLocation().getZipCode() != null) {
					department.getLocation().getZipCode().getId();
					if (department.getLocation().getZipCode().getCity() != null) {
						department.getLocation().getZipCode().getCity().getId();
						department.getLocation().getZipCode().getCity().getName();
					}	
					if (department.getLocation().getZipCode().getZip() != null) {
						department.getLocation().getZipCode().getZip().getId();
						if (department.getLocation().getZipCode().getZip().getCountry() != null) {
							department.getLocation().getZipCode().getZip().getCountry().getId();
							department.getLocation().getZipCode().getZip().getCountry().getName();
						}
						if (department.getLocation().getZipCode().getZip().getCounty() != null) {
							department.getLocation().getZipCode().getZip().getCounty().getId();
							department.getLocation().getZipCode().getZip().getCounty().getName();
						}	
						if (department.getLocation().getZipCode().getZip().getState() != null) {
							department.getLocation().getZipCode().getZip().getState().getId();
							department.getLocation().getZipCode().getZip().getState().getName();																					
						}	
					}
				}
			}
		}
		if (department.getBudget() != null) {
			department.getBudget().getName();
		}
		//#12512
		// KKORNEL: AES-13304
		if ((department.getParent() != null) && (department.getParent().getKind() != null) && (department.getParent().getKind() == NodeKind.BUSINESS_GROUP)) {
			BusinessGroup bg = sm.get(BusinessGroup.class, department.getParent().getId());
			bg.getId();
			bg.getName();
			bg.getKind();
			bg.getLevel();
			department.setParent(bg);
		}
		department.getKind();
	}
}
